home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 276_01 / a16.c < prev    next >
C/C++ Source or Header  |  1989-10-01  |  10KB  |  407 lines

  1. /*
  2.     HEADER:        CUG276;
  3.     TITLE:        PIC1650 Cross-Assembler (Portable);
  4.     FILENAME:    A16.C;
  5.     VERSION:    0.0;
  6.     DATE:        06/15/1989;
  7.     SEE-ALSO:    A16.H;
  8.     AUTHORS:    William C. Colley III;
  9. */
  10.  
  11. /*
  12.              PIC1650 Cross-Assembler in Portable C
  13.  
  14.          Copyright (c) 1985,1987,1989 William C. Colley, III
  15.  
  16. Revision History:
  17.  
  18. Ver    Date        Description
  19.  
  20. 0.0    JUNE 1989    Derived from version 0.2 of my portable 8085 cross-
  21.             assembler.  WCC3.
  22.  
  23. This file contains the main program and line assembly routines for the
  24. assembler.  The main program parses the command line, feeds the source lines
  25. to the line assembly routine, and sends the results to the listing and object
  26. file output routines.  It also coordinates the activities of everything.  The
  27. line assembly routines uses the expression analyzer and the lexical analyzer
  28. to parse the source line and convert it into the object bytes that it
  29. represents.
  30. */
  31.  
  32. /*  Get global goodies:  */
  33.  
  34. #include "a16.h"
  35.  
  36. /*  Define global mailboxes for all modules:                */
  37.  
  38. char errcode, line[MAXLINE + 1], title[MAXLINE];
  39. int pass = 0;
  40. int eject, filesp, forwd, listhex;
  41. unsigned  address, bytes, errors, listleft, obj[MAXLINE], pagelen, pc;
  42. FILE *filestk[FILES], *source;
  43. TOKEN token;
  44.  
  45. /*  Mainline routine.  This routine parses the command line, sets up    */
  46. /*  the assembler at the beginning of each pass, feeds the source text    */
  47. /*  to the line assembler, feeds the result to the listing and hex file    */
  48. /*  drivers, and cleans everything up at the end of the run.        */
  49.  
  50. static int done, ifsp, off;
  51.  
  52. void main(argc,argv)
  53. int argc;
  54. char **argv;
  55. {
  56.     SCRATCH unsigned *o;
  57.     int newline();
  58.     void asm_line();
  59.     void lclose(), lopen(), lputs();
  60.     void hclose(), hopen(), hputc();
  61.     void error(), fatal_error(), warning();
  62.  
  63.     printf("PIC1650 Cross-Assembler (Portable) Ver 0.0\n");
  64.     printf("Copyright (c) 1985,1987,1989 William C. Colley, III\n\n");
  65.  
  66.     while (--argc > 0) {
  67.     if (**++argv == '-') {
  68.         switch (toupper(*++*argv)) {
  69.         case 'L':   if (!*++*argv) {
  70.                 if (!--argc) { warning(NOLST);  break; }
  71.                 else ++argv;
  72.                 }
  73.                 lopen(*argv);
  74.                 break;
  75.  
  76.         case 'O':   if (!*++*argv) {
  77.                 if (!--argc) { warning(NOHEX);  break; }
  78.                 else ++argv;
  79.                 }
  80.                 hopen(*argv);
  81.                 break;
  82.  
  83.         default:    warning(BADOPT);
  84.         }
  85.     }
  86.     else if (filestk[0]) warning(TWOASM);
  87.     else if (!(filestk[0] = fopen(*argv,"r"))) fatal_error(ASMOPEN);
  88.     }
  89.     if (!filestk[0]) fatal_error(NOASM);
  90.  
  91.     while (++pass < 3) {
  92.     fseek(source = filestk[0],0L,0);  done = off = FALSE;
  93.     errors = filesp = ifsp = pagelen = pc = 0;  title[0] = '\0';
  94.     while (!done) {
  95.         errcode = ' ';
  96.         if (newline()) {
  97.         error('*');
  98.         strcpy(line,"\tEND\n");
  99.         done = eject = TRUE;  listhex = FALSE;
  100.         bytes = 0;
  101.         }
  102.         else asm_line();
  103.         pc = word(pc + bytes);
  104.         if (pass == 2) {
  105.         lputs();
  106.         for (o = obj; bytes--; hputc(*o++));
  107.         }
  108.     }
  109.     }
  110.  
  111.     fclose(filestk[0]);  lclose();  hclose();
  112.  
  113.     if (errors) printf("%d Error(s)\n",errors);
  114.     else printf("No Errors\n");
  115.  
  116.     exit(errors);
  117. }
  118.  
  119. /*  Line assembly routine.  This routine gets expressions and tokens    */
  120. /*  from the source file using the expression evaluator and lexical    */
  121. /*  analyzer, respectively.  It fills a buffer with the machine code    */
  122. /*  bytes and returns nothing.                        */
  123.  
  124. static char label[MAXLINE];
  125. static int ifstack[IFDEPTH] = { ON };
  126.  
  127. static OPCODE *opcod;
  128.  
  129. void asm_line()
  130. {
  131.     SCRATCH char *p;
  132.     SCRATCH int i;
  133.     int isalph(), popc();
  134.     OPCODE *find_code(), *find_operator();
  135.     void do_label(), flush(), normal_op(), pseudo_op();
  136.     void error(), pops(), pushc(), trash();
  137.  
  138.     address = pc;  bytes = 0;  eject = forwd = listhex = FALSE;
  139.     for (i = 0; i < BIGINST; obj[i++] = NOP);
  140.  
  141.     label[0] = '\0';
  142.     if ((i = popc()) != ' ' && i != '\n') {
  143.     if (isalph(i)) {
  144.         pushc(i);  pops(label);
  145.         for (p = label; *p; ++p);
  146.         if (*--p == ':') *p = '\0';
  147.         if (find_operator(label)) { label[0] = '\0';  error('L'); }
  148.     }
  149.     else {
  150.         error('L');
  151.         while ((i = popc()) != ' ' && i != '\n');
  152.     }
  153.     }
  154.  
  155.     trash(); opcod = NULL;
  156.     if ((i = popc()) != '\n') {
  157.     if (!isalph(i)) error('S');
  158.     else {
  159.         pushc(i);  pops(token.sval);
  160.         if (!(opcod = find_code(token.sval))) error('O');
  161.     }
  162.     if (!opcod) { listhex = TRUE;  bytes = BIGINST; }
  163.     }
  164.  
  165.     if (opcod && opcod -> attr & ISIF) { if (label[0]) error('L'); }
  166.     else if (off) { listhex = FALSE;  flush();  return; }
  167.  
  168.     if (!opcod) { do_label();  flush(); }
  169.     else {
  170.     listhex = TRUE;
  171.     if (opcod -> attr & PSEUDO) pseudo_op();
  172.     else normal_op();
  173.     while ((i = popc()) != '\n') if (i != ' ') error('T');
  174.     }
  175.     source = filestk[filesp];
  176.     return;
  177. }
  178.  
  179. static void flush()
  180. {
  181.     while (popc() != '\n');
  182. }
  183.  
  184. static void do_label()
  185. {
  186.     SCRATCH SYMBOL *l;
  187.     SYMBOL *find_symbol(), *new_symbol();
  188.     void error();
  189.  
  190.     if (label[0]) {
  191.     listhex = TRUE;
  192.     if (pass == 1) {
  193.         if (!((l = new_symbol(label)) -> attr)) {
  194.         l -> attr = FORWD + VAL;
  195.         l -> valu = pc;
  196.         }
  197.     }
  198.     else {
  199.         if (l = find_symbol(label)) {
  200.         l -> attr = VAL;
  201.         if (l -> valu != pc) error('M');
  202.         }
  203.         else error('P');
  204.     }
  205.     }
  206. }
  207.  
  208. static void normal_op()
  209. {
  210.     SCRATCH unsigned a, *o, u;
  211.     unsigned expr();
  212.     TOKEN *lex();
  213.     void do_label(), error(), unlex();
  214.  
  215.     do_label();  bytes = (a = opcod -> attr) & BYTES;
  216.     if (pass < 2) return;
  217.     *(o = obj) = opcod -> valu;
  218.     if (bytes == 2) *++o = 0xa00;
  219.     if (a & ARG1) {
  220.     u = expr();
  221.     switch (a & ARG1) {
  222.         case ADDR_9:    if (u > 0x1ff) { u = 0;  error('A'); }
  223.                 break;
  224.  
  225.         case ADDR_8:    if (u > 0x0ff) { u = 0;  error('A'); }
  226.                 break;
  227.  
  228.         case IMMED_8:   if (u > 0xff && u < 0xff80) {
  229.                 u = 0;  error('V');
  230.                 }
  231.                 else u &= 0xff;
  232.                 break;
  233.  
  234.         case REG_5:        if (u > 0x1f) { u = 0;  error('R'); }
  235.                 break;
  236.  
  237.         case TRIS_REG:  if (u > 7 || u < 5) { u = 5;  error('R'); }
  238.                 break;
  239.     }
  240.     *o += u;
  241.     }
  242.     if (a & ARG2) {
  243.     if ((lex() -> attr & TYPE) != SEP) { unlex();  error('S'); }
  244.     else {
  245.         u = expr();
  246.         switch (a & ARG2) {
  247.         case BIT_3: if (u > 7) { u = 0;  error('B'); }
  248.                 break;
  249.  
  250.         case DIR:   if (u > 1) { u = 0;  error('W'); }
  251.         }
  252.         *o += u << 5;
  253.     }
  254.     }
  255.     return;
  256. }
  257.  
  258. static void pseudo_op()
  259. {
  260.     SCRATCH unsigned *o, u;
  261.     SCRATCH SYMBOL *l;
  262.     int popc();
  263.     unsigned expr();
  264.     SYMBOL *find_symbol(), *new_symbol();
  265.     TOKEN *lex();
  266.     void do_label(), error(), fatal_error(), hseek();
  267.     void pushc(), trash(), unlex();
  268.  
  269.     o = obj;
  270.     switch (opcod -> valu) {
  271.     case DS:    do_label();
  272.             u = word(pc + expr());
  273.             if (forwd) error('P');
  274.             else {
  275.             pc = u;
  276.             if (pass == 2) hseek(pc);
  277.             }
  278.             break;
  279.  
  280.     case DW:    do_label();
  281.             do {
  282.             lex();  unlex();  ++bytes;
  283.             u = ((token.attr & TYPE) == SEP) ? 0 : expr();
  284.             if (u > 0x0fff && u < 0xf800) {
  285.                 *o++ = 0;  error('V');
  286.             }
  287.             else *o++ = u;
  288.             } while ((lex() -> attr & TYPE) == SEP);
  289.             break;
  290.  
  291.     case ELSE:  listhex = FALSE;
  292.             if (ifsp) off = (ifstack[ifsp] = -ifstack[ifsp]) != ON;
  293.             else error('I');
  294.             break;
  295.  
  296.     case END:   do_label();
  297.             if (filesp) { listhex = FALSE;  error('*'); }
  298.             else {
  299.             done = eject = TRUE;
  300.             if (pass == 2) {
  301.                 if ((lex() -> attr & TYPE) != EOL) {
  302.                 unlex();  hseek(address = expr());
  303.                 }
  304.             }
  305.             if (ifsp) error('I');
  306.             }
  307.             break;
  308.  
  309.     case ENDIF: listhex = FALSE;
  310.             if (ifsp) off = ifstack[--ifsp] != ON;
  311.             else error('I');
  312.             break;
  313.  
  314.     case EQU:   if (label[0]) {
  315.             if (pass == 1) {
  316.                 if (!((l = new_symbol(label)) -> attr)) {
  317.                 l -> attr = FORWD + VAL;
  318.                 address = expr();
  319.                 if (!forwd) l -> valu = address;
  320.                 }
  321.             }
  322.             else {
  323.                 if (l = find_symbol(label)) {
  324.                 l -> attr = VAL;
  325.                 address = expr();
  326.                 if (forwd) error('P');
  327.                 if (l -> valu != address) error('M');
  328.                 }
  329.                 else error('P');
  330.             }
  331.             }
  332.             else error('L');
  333.             break;
  334.  
  335.